// Copyright (c) 2022 Presto Labs Pte. Ltd.
// Author: qiang

#pragma once

#include <string>

#include <rapidjson/document.h>

#include "coin/proto/coin_query.pb.h"

namespace coin2::exchange::apollox::order_v1 {

namespace error_code {

inline int32_t GetErrorCodeAsInt(
    const rapidjson::GenericValue<rapidjson::UTF8<>>& json_error_code) {
  int32_t error_code = 0;
  if (json_error_code.IsInt()) {
    error_code = json_error_code.GetInt();
  } else if (json_error_code.IsString() && std::strlen(json_error_code.GetString()) > 0) {
    error_code = std::stoi(json_error_code.GetString());
  }
  return error_code;
}

inline std::string GetExchangeOrderErrorCode(
    const rapidjson::GenericValue<rapidjson::UTF8<>>& json) {
  if (json.HasMember("code")) {
    return std::to_string(GetErrorCodeAsInt(json["code"]));
  } else {
    return {};
  }
}

inline std::string GetExchangeOrderErrorMsg(
    const rapidjson::GenericValue<rapidjson::UTF8<>>& json) {
  if (json.HasMember("msg")) {
    return json["msg"].GetString();
  } else {
    return {};
  }
}

inline coin::proto::OrderErrorCode GetOrderErrorCode(
    const rapidjson::GenericValue<rapidjson::UTF8<>>& json_error_code,
    const rapidjson::GenericValue<rapidjson::UTF8<>>& json_error_msg,
    bool has_exchange_order_id) {
  using coin::proto::OrderErrorCode;
  auto result = coin::proto::OrderErrorCode::ORDER_UNKNOWN_ERROR;
  int32_t error_code = GetErrorCodeAsInt(json_error_code);
  std::string error_msg = json_error_msg.GetString();

  if (error_code == 200) {
    result = OrderErrorCode::ORDER_NO_ERROR;
  } else if (error_code == -6012) {
    result = OrderErrorCode::SUBMIT_ORDER_INSUFFICIENT_FUND;
  } else if (error_code == -6018) {
    result = OrderErrorCode::SUBMIT_ORDER_INSUFFICIENT_FUND;
  } else if (error_msg == "Account has insufficient balance for requested action.") {
    result = OrderErrorCode::SUBMIT_ORDER_INSUFFICIENT_FUND;
  } else if (error_code == -2013) {
    result = OrderErrorCode::ORDER_NOT_FOUND;
  } else if (error_code == -2011) {
    if (error_msg == "Unknown order sent.") {
      result = OrderErrorCode::ORDER_NOT_FOUND;
    }
  }
  // TODO(linchuan): is there ORDER_FILLED_ALREADY or ORDER_CANCELED_ALREADY?

  return result;
}

}  // namespace error_code

}  // namespace coin2::exchange::apollox::order_v1
